package puffer.starter.db.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import puffer.starter.db.entity.Dnt;
import puffer.starter.db.entity.Page;
import puffer.starter.db.mapper.DMapper;
import puffer.starter.db.strengthen.Wrapper;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;


/**
 * 增强Dao实现类
 *
 * @author 王永吉
 */
@Service
public class DaoImpl implements Dao {

    @Autowired
    private DMapper pfMapper;

    @Override
    public long insertOrigin(String sql) {
        return pfMapper._insertOrigin_(sql);
    }

    @Override
    public long insert(String tableName, Dnt entity) {
//        DbHelp.insertFile(entity);
        return pfMapper._insert_(tableName, entity);
    }

    @Override
    public long insertBatch(String tableName, List<Dnt> entityList) {
        return insertBatch(tableName, entityList, entityList.size());
    }

    @Override
    public long insertBatch(String tableName, List<Dnt> entityList, int batchSize) {
//        for (Dnt entity : entityList) {
//            DbHelp.insertFile(entity);
//        }
        if (entityList.size() == 0) return 0;
        HashSet columns = new HashSet(entityList.get(0).keySet());

        long addCount = 0;
        int cycleCount = entityList.size() / batchSize;

        for (int i = 0; i < cycleCount; i++) {
            addCount += pfMapper._insertBatch_(tableName, columns, entityList.subList(i * batchSize, (i + 1) * batchSize));
        }
        int yu = entityList.size() % batchSize;
        if (yu > 0) {
            addCount += pfMapper._insertBatch_(tableName, columns, entityList.subList(cycleCount * batchSize, (cycleCount * batchSize) + yu));
        }
        return addCount;
    }

    @Override
    public long deleteOrigin(String sql) {
        return pfMapper._deleteOrigin_(sql);
    }

    @Override
    public long delete(String tableName, Wrapper<Object> wrapper) {
        return pfMapper._delete_(tableName, wrapper);
    }

    @Override
    public long deleteById(String tableName, Serializable id) {
        return deleteById(tableName, "id", id);
    }

    public long deleteById(String tableName, String idColumn, Serializable id) {
        return pfMapper._deleteById_(tableName, id, idColumn);
    }

    @Override
    public long deleteByIds(String tableName, Collection<Serializable> ids) {
        return deleteByIds(tableName, ids, ids.size());
    }

    @Override
    public long deleteByIds(String tableName, Collection<Serializable> ids, int batchSize) {
        return deleteByIds(tableName, "id", ids, ids.size());
    }

    public long deleteByIds(String tableName, String idColumn, Collection<Serializable> ids) {
        return deleteByIds(tableName, idColumn, ids, ids.size());
    }

    public long deleteByIds(String tableName, String idColumn, Collection<Serializable> ids, int batchSize) {
        if (ids.size() == 0) return 0;
        ArrayList<Serializable> idList = new ArrayList<>(ids);
        long deleteCount = 0;
        int cycleCount = ids.size() / batchSize;

        for (int i = 0; i < cycleCount; i++) {
            deleteCount += pfMapper._deleteByIds_(tableName, idList.subList(i * batchSize, (i + 1) * batchSize), idColumn);
        }
        int yu = idList.size() % batchSize;
        if (yu > 0) {
            deleteCount += pfMapper._deleteByIds_(tableName, idList.subList(cycleCount * batchSize, (cycleCount * batchSize) + yu), idColumn);
        }
        return deleteCount;
    }


    @Override
    public long updateOrigin(String sql) {
        return pfMapper._updateOrigin_(sql);
    }

    @Override
    public long update(String tableName, Dnt entity, Wrapper<Object> wrapper) {
//        DbHelp.updateFile(entity);
        return pfMapper._update_(tableName, entity, wrapper.getSqlSet(), wrapper);
    }

    @Override
    public long update(String tableName, Wrapper<Object> wrapper) {
        return pfMapper._update_(tableName, null, wrapper.getSqlSet(), wrapper);
    }

    @Override
    public long updateById(String tableName, Dnt entity) {
        return updateById(tableName, "id", entity, entity.getString("id"));
    }

    @Override
    public long updateById(String tableName, Dnt entity, String idKey) {
        return updateById(tableName, idKey, entity, entity.getString(idKey));
    }

    public long updateById(String tableName, String id_column, Dnt entity, Serializable id) {
//        DbHelp.updateFile(entity);
        return pfMapper._updateById_(tableName, entity, id_column, id);
    }

    @Override
    public long updateBatchById(String tableName, List<Dnt> entityList) {
        return updateBatchById(tableName, "id", entityList, entityList.size());
    }

    @Override
    public long updateBatchById(String tableName, List<Dnt> entityList, String idKey) {
        return updateBatchById(tableName, idKey, entityList, entityList.size());
    }


    public long updateBatchById(String tableName, String idColumn, List<Dnt> entityList) {
        return updateBatchById(tableName, idColumn, entityList, entityList.size());
    }

    @Override
    public long updateBatchById(String tableName, List<Dnt> entityList, int batchSize) {
        return updateBatchById(tableName, "id", entityList, batchSize);
    }

    @Override
    public long updateBatchById(String tableName, List<Dnt> entityList, String idKey, int batchSize) {
        return updateBatchById(tableName, idKey, entityList, batchSize);
    }

    public long updateBatchById(String tableName, String idColumn, List<Dnt> entityList, int batchSize) {
//        for (Dnt entity : entityList) {
//            DbHelp.updateFile(entity);
//        }

        if (entityList.size() == 0) return 0;
        HashSet columns = new HashSet(entityList.get(0).keySet());

        long updateCount = 0;
        int cycleCount = entityList.size() / batchSize;

        for (int i = 0; i < cycleCount; i++) {
            updateCount += pfMapper._updateBatchById_(tableName, columns, entityList.subList(i * batchSize, (i + 1) * batchSize), idColumn);
        }
        int yu = entityList.size() % batchSize;
        if (yu > 0) {
            updateCount += pfMapper._updateBatchById_(tableName, columns, entityList.subList(cycleCount * batchSize, (cycleCount * batchSize) + yu), idColumn);
        }
        return updateCount;
    }

    @Override
    public Dnt selectOneOrigin(String sql) {
        return pfMapper._selectOneOrigin_(sql);
    }

    @Override
    public Object selectObjOrigin(String sql) {
        return pfMapper._selectObjOrigin_(sql);
    }

    @Override
    public Dnt selectOne(String tableName, Wrapper<Object> wrapper) {
        return pfMapper._selectOne_(tableName, wrapper);
    }

    @Override
    public Object selectObj(String tableName, Wrapper<Object> wrapper) {
        return pfMapper._selectObj_(tableName, wrapper);
    }

    @Override
    public List<Dnt> listOrigin(String sql) {
        return pfMapper._listOrigin_(sql);
    }

    @Override
    public List<Object> listObjOrigin(String sql) {
        return pfMapper._listObjOrigin_(sql);
    }

    @Override
    public <T> List<T> listObjOrigin(String sql, Class<T> t) {
        return (List<T>) pfMapper._listObjOrigin_(sql);
    }

    @Override
    public List<Dnt> list(String tableName, Wrapper<Object> wrapper) {
        return pfMapper._list_(tableName, wrapper);
    }

    @Override
    public List<Object> listObj(String tableName, Wrapper<Object> wrapper) {
        return pfMapper._listObj_(tableName, wrapper);
    }

    @Override
    public <T> List<T> listObj(String tableName, Wrapper<Object> wrapper, Class<T> t) {
        return (List<T>) pfMapper._listObj_(tableName, wrapper);
    }

    @Override
    public long count(String tableName, Wrapper<Object> wrapper) {
        return pfMapper._count_(tableName, wrapper);
    }

    @Override
    public long countOrigin(String sql) {
        return pfMapper._countOrigin_(sql);
    }

    @Override
    public Page<Dnt> page(String tableName, Page page) {
        Wrapper<Object> wrapper = new Wrapper<>();
        wrapper.select("*");
        wrapper.eq("1", "1");
        return page(tableName, wrapper, page);
    }

    @Override
    public Page<Dnt> page(String tableName, Wrapper<Object> wrapper, Page page) {
        long current = page.getCurrent();
        long size = page.getSize();
        page.setTotal(list(tableName, wrapper).size());
        long pages = (page.getTotal() + size - 1) / size;
        page.setPages(pages);
        page.setFirst(current == 1);
        page.setLast(current == page.getPages());
        List<Dnt> ents = pfMapper._pageWrapper_(tableName, wrapper, ((current - 1) * size), size);
        page.setData(ents);
        return page;
    }

    @Override
    public Page<Dnt> pageOrigin(String sql, Page page) {
        long current = page.getCurrent();
        long size = page.getSize();
        page.setTotal(listOrigin(sql).size());
        long pages = (page.getTotal() + size - 1) / size;
        page.setPages(pages);
        page.setFirst(current == 1);
        page.setLast(current == page.getPages());
        List<Dnt> ents = pfMapper._pageOrigin_(sql, ((current - 1) * size), size);
        page.setData(ents);
        return page;
    }


}
